package com.dustedpixels.jasmin.memory.impl;

import com.dustedpixels.jasmin.memory.implbase.Memory16x8ImplBase;

/**
 * A block of Random Access Memory of specified address bus width.
 */
public class RAMBlock16x8 extends Memory16x8ImplBase {
    private final byte[] array;
    private final short mask;
    
    public static RAMBlock16x8 create(int addressBits) {
        if (addressBits > 16 || addressBits <= 0) {
            throw new IllegalArgumentException("AddressBits must be in 1..16 range.");
        }
        
        int arrayLength = 1 << addressBits;
        short mask = (short) (arrayLength - 1);
        
        return new RAMBlock16x8(mask, new byte[arrayLength]);
    }
    
    public static RAMBlock16x8 create(int addressBits, byte[] array) {
        if (addressBits > 16 || addressBits <= 0) {
            throw new IllegalArgumentException("AddressBits must be in 1..16 range.");
        }
        
        int arrayLength = 1 << addressBits;
        
        if (array.length != arrayLength) {
            throw new IllegalArgumentException("Array length should be " + arrayLength);
        }
        
        short mask = (short) (arrayLength - 1);
        
        return new RAMBlock16x8(mask, array);
    }
    
    RAMBlock16x8(short mask, byte[] array) {
        this.array = array;
        this.mask = mask;
    }
    
    public byte peek(short address) {
        return array[address & mask];
    }

    public void poke(short address, byte value) {
        array[address & mask] = value;
    }

    public byte fastPeek(short address) {
        return array[address];
    }

    public void fastPoke(short address, byte data) {
        array[address] = data;
    }

    public short getAddressMask() {
        return mask;
    }
}
